v5.2.1 修复报告:二级源 VIX 回退失效 + 债券腿"盘中伪收盘"
scripts/dkanalysis.py L0-2 分支的回退守卫写成:
v5.2.1 修复报告:二级源 VIX 回退失效 + 债券腿"盘中伪收盘"
生成时间:2026-09-26T01:20:00+08:00
触发:2026-09-25「执行开盘日任务」首次运行(
run_id 20260925T235746+0800)出现 L0 由「正常」回退为「降级」 + 排版 2 项告警性质:两个真实代码缺陷(非数据源问题、非数据缺失)
结论:已修复 + 备份 + 回归测试 + 重发验证;
arch_check 10/10 ✔、doc_sync_check全绿、测试全绿状态:已落地生产库
一、缺陷 P1-1|二级源 VIX 回退在"二级源比目标日更新"时整段失效
症状
- 目标日 =
2026-09-24,权威源 FREDVIXCLS仅到2026-09-22(未发布)。 - 二级源
数据/vix_daily.json已含2026-09-25的 T+0 延迟报价(CBOE),且2026-09-23/09-24已由 CBOE 官方日线 CSV 权威覆盖。 - 结果:
L0-2 = 无法评估(note: "VIX 未更新到目标日(最近 2026-09-22)")→L0 汇总 = 降级(存在无法评估项),模拟盘state_snapshot.L0随之变为「降级」。 - 与预期相反:二级源明明已有目标日的权威值,却完全没被用上。
根因
scripts/dkanalysis.py L0-2 分支的回退守卫写成:
ds, closes, _srcs = dkaux.vix_series(aux) # ds = 全部日期升序,含 09-25
tkey = str(target.date()) # '2026-09-24'
if ds and ds[-1] == tkey: # ← 错:要求“序列末项 == 目标日”
...T+0 延迟报价天生会比目标日更新(黄金目标停留在 09-24 时,VIX 已有 09-25 盘中值), 序列末项变成 2026-09-25 → 守卫不成立 → 回退整段失效。 上一次(20260925T153432+0800)恰好因为 VIX 序列末项也是 09-24 才"看起来正常", 属于偶合通过。
修复
upto = [d for d in ds if d <= tkey] # 只看目标日及之前
if upto and upto[-1] == tkey: # 只要“目标日在序列内”
...
prev_used = upto[-2] if len(upto) >= 2 else None # 前值取“目标日之前”而非序列倒数第二
vix_src = _SRC_LABEL.get(dkaux.vix_source_of(aux, tkey) or "", "二级源")附带改进:来源标签改为按实际源映射(cboe_csv → CBOE 官方日线 CSV、 cboe_delayed → CBOE 延迟报价(T+0)、fred → FRED VIXCLS、cboe_delayed_derived → 反推), 不再一律写"延迟报价(T+0)"从而低估权威性。
红线保持(回归测试断言)
- 权威源已有目标日值时绝不被二级源顶替(
vix_src == "FRED VIXCLS"); - 无二级源时行为不变(仍
无法评估); - 前值为反推值时必须标
[待验证];为权威 CSV 时不应再标。
验证(重发后真实数据)
L0-2 VIX 跳升 | 正常 | 单日 +3.2%, 三日 +5.4% | 来源:CBOE 官方日线 CSV;权威源尚未发布到目标日,暂用二级源回退
L0 汇总 = 正常(L0-3 可评估) aux_sources: vix_used=CBOE 官方日线 CSV, l0_aux_used=true二、缺陷 P1-2|债券腿把当日"盘中未完成"日线当收盘永久并入
症状
- 抓取时刻 =
2026-09-25 23:57 CST=15:57 UTC= 美股 09-25 盘中(开盘约 2.5 小时)。 - 东财日线
push2his接口在盘中即返回当日未完成中间价:
['2026-09-22,96.250', '2026-09-23,95.410', '2026-09-24,94.950', '2026-09-25,94.925'] (纳斯达克官网权威 tradesTable 末行仍为 09/24/2026, 94.95,totalRecords=81)
TLT/AGG因此被写入2026-09-25(TLT 79.095 / AGG 94.925),条数 81 → 82。- 危害被放大:合并规则是「已有日期不覆盖」(不补数红线),所以这个"伪收盘"
会永久留在库里,污染 09-25 的债券日回报与 L0-3 债券腿 —— 直接违反 「不制造当日尚未发生的价格」。
根因
scripts/update_bond_etf.py 只按日期做增量合并,没有任何"该日是否已收盘"的判定。
修复
新增会话完成判定与过滤:
def _is_session_final(d, now=None):
"""美股 16:00 ET 收盘(夏令时 20:00Z / 冬令时 21:00Z)→ 保守取 UTC 21:00。
now_utc >= D 21:00Z 才算"最终收盘"。"""
def filter_session_final(series, now=None): # 拆「最终收盘」与「盘中未完成」merge_asset(..., now=None, drop_dates=None):
- 纳斯达克与东财两侧都过滤非最终收盘日期 → 进
provisional_dropped(不写入); - 旧文件中非最终收盘日期同样被剪除(可回滚同轮已污染的行);
drop_dates= 上一轮 payload 的provisional_dropped.dates→ 剪除历史遗留的盘中伪收盘并重取真值(自愈),由main()读取旧 payload 自动传入。
验证(真实数据回滚 + 自愈)
TLT: 82 天 → 81 天|最新 2026-09-24,79.42
⚠ 盘中未完成、未并入: ['2026-09-25']
AGG: 82 天 → 81 天|最新 2026-09-24,94.95
⚠ 盘中未完成、未并入: ['2026-09-25']
交叉验证: 两源真实收盘一致(≤0.01)(重叠 81 日)数据/bond_agg.json.provisional_dropped = {dates:[2026-09-25], rule:"…[待验证]"};- 面板 09-25 行的
tlt/agg已清空(该行lbma_priced=False、trading_day=False,不计入任何统计); - 09-25 收盘发布后,下一轮会正常并入(UTC 21:00Z 之后判定通过)。
三、同步与自检
| 项 | 变更 |
|---|---|
| 驾驶舱头部面板规模 | 84 行 → 85 行/区间 06-01→09-25 |
| 驾驶舱页脚日期 | 2026-09-25 → 2026-09-26 |
| 驾驶舱 §〇·五 复盘地图 | 99 → 100 直属(新增 09-25 盘前简报) |
| 驾驶舱 §九 | 新增 v5.2.1 版本记录(本报告) |
| 复盘新增 | 复盘/2026-09-25 盘前简报.md(review_write.py 落盘,✔ 导航页可直达) |
| 排版同步 | doc_sync_check --strict rc=0 全绿 |
| 架构自检 | arch_check 10/10 ✔(死链 0 / 孤儿 0 / 0 个点不到) |
回归测试(新增 3 项)
| 类 | 测试 | 断言 |
|---|---|---|
AuxSourceTests | test_aux_newer_than_target_still_falls_back | 二级源含 目标日 + 更晚日期 时回退仍生效;vix_src == "CBOE 官方日线 CSV";权威前值不再标 [待验证] |
BondLegTests | test_intraday_bar_is_not_merged_as_close | 盘中(UTC 15:57)的 09-25 日线不入库,进 provisional_dropped |
BondLegTests | test_post_close_bar_is_merged_and_marked_row_is_self_healed | 收盘后正常并入;上轮标记的伪收盘被剪除并重取真值 |
测试批次(iSH 必须分批/串行):BondLegTests+AuxSourceTests 11 OK; DocSyncTests+PathGuardTests 8 OK;PatternAbcTests+RegimeWfTests+PaperShortReduceTests 13 OK; PaperEngineTests 5 OK;PipelineSafetyTests 逐项运行。
四、回滚点
/var/minis/shared/backup/DUCKERRY_pre_auxvixfix_20260925/dkanalysis.py(md5050b6b3459fb5976fb9b7a28cead3121)update_bond_etf.py(md52699d83443dd3cce29b590cd8191390b)bond_agg.json/bond_tlt.json(含 09-25 伪收盘的污染版)md5_before.txt
五、遗留(未变)
[P1]09-25 LBMA PM / 债券腿收盘未发布 → 09-25 预测批次保持pending。[P1]事件日历只覆盖到 09-24 → 前向事件覆盖缺失。[P2]美股指数二级源为东财单家(与 FRED 79→81 日逐日一致)→ 集中度[待验证]。[待验证]_is_session_final的 UTC 21:00 保守界、provisional_dropped规则本身均未经过长期样本外验证;
半日市(如感恩节翌日 13:00 ET 收盘)会用更早的收盘时间 → 当前规则更保守(不会误并入),方向安全。